#***********************************************************************************************************************
# File Name       : hex_merge.py
# Description     :
# Original Author : Chao Wang
# Created on      : August 2, 2021, 5:15 PM
#***********************************************************************************************************************
from __future__ import print_function
import sys

try:
    import argparse
    from intelhex import IntelHex
    import os
except ImportError:
    sys.exit("""ImportError: You are probably missing some modules.
To add needed modules, run like 'python -m pip install -U intelhex'""")

#-----------------------------------------------------------------------------------------------------------------------
# Generate help and use messages
parser = argparse.ArgumentParser(
    description='hex merge for app and boot_end_address.',
    epilog='Example: hex_merge.py ./App/Release/App.hex ./Boot/Release/Boot.hex ./App/Release/Merged.hex 0x0 0x3FF',
    formatter_class=argparse.RawTextHelpFormatter)

parser.add_argument('app_file', help='App hex file will be uploaded')
parser.add_argument('boot_file', help='Boot hex file will be uploaded')
parser.add_argument('merged_file', help='Merged hex file will be updated')
parser.add_argument('boot_start_address', help='Boot start address for merging')
parser.add_argument('boot_end_address', help='Boot end address for merging')
parser.add_argument('flash_size', help='flash size')

if len(sys.argv) != 7:
    parser.print_help()
    sys.exit(1)

args = parser.parse_args()

# Command line arguments
AppFile = sys.argv[1]
BootFile = sys.argv[2]
MergedFile = sys.argv[3]
BootStartAddressInBytes = int(sys.argv[4], 16)
BootEndAddressInBytes = int(sys.argv[5], 16)
FlashSizeInBytes = int(sys.argv[6], 16)

#-----------------------------------------------------------------------------------------------------------------------
# Variables

#***********************************************************************************************************************
# Function : hex2bin(hex_file, flash_start, flash_end)
#***********************************************************************************************************************
def hex2bin(hex_file, flash_start, flash_end):
    # Load application hex file and convert to bin file
    ih = IntelHex()
    fileextension = hex_file[-3:]
    ih.loadfile(hex_file, format=fileextension)

    app_bin = ih.tobinarray(start=flash_start, end=(flash_end - 1))

    bin_file = os.path.splitext(hex_file)[0] + ".bin"

    # Save original file
    fq = open(bin_file, 'wb')
    fq.write(app_bin)
    fq.close()

#***********************************************************************************************************************
# Function : merge_hex(app_file, boot_file, combined_file, start_addr4merge, end_addr4merge, flash_size)
#***********************************************************************************************************************
def merge_hex(app_file, boot_file, combined_file, start_addr4merge, end_addr4merge, flash_size):
    if os.path.exists(combined_file):
      os.remove(combined_file)
      
    fq = open(combined_file, 'wb')
    fq.close()
    
    app = IntelHex(app_file)
    boot = IntelHex(boot_file)
    merged = IntelHex(combined_file)
    
    
    merged.merge(boot[start_addr4merge:(end_addr4merge+1)], overlap='replace') # not include address (end_addr4merge+2), till to end_addr4merge+1
    merged.merge(app[(end_addr4merge+1):], overlap='replace')
    merged.write_hex_file(combined_file)
    
    hex2bin(app_file, 0x0, FlashSizeInBytes)
    hex2bin(boot_file, 0x0, FlashSizeInBytes)
    hex2bin(combined_file, 0x0, FlashSizeInBytes)
    

#***********************************************************************************************************************
# Function : main
#***********************************************************************************************************************
if __name__ == "__main__":
    os.system('')
    print("\033[1;34;40m")  
    merge_hex(AppFile, BootFile, MergedFile, BootStartAddressInBytes, BootEndAddressInBytes, FlashSizeInBytes)
    print("****************Hex Merged Successful!******************\n")

    print("\033[0m")
    